package com.imi.sdk.jnitest


import android.opengl.GLES20
import com.imi.sdk.render.Renderable
import com.imi.sdk.render.ShaderUtils
import java.nio.ByteBuffer
import java.nio.ByteOrder
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

//

class TextureRenderable1 (internal var w: Int, internal var h: Int) : Renderable {

    internal var mVertices = floatArrayOf(-1f, -1f, 1f, -1f, -1f, 1f, 1f, 1f)

    internal var mCoords = floatArrayOf( 0f, 1f,1f, 1f, 0f, 0f, 1f, 0f)

    internal lateinit var bufVertices: ByteBuffer
    internal lateinit var bufCoords: ByteBuffer

    internal var textureId = 0

    internal val mNVert = 4

    var onDraw: (Int) -> Unit = {}

    var vertexSource = "attribute vec2 aPosition;\n" +
            "attribute vec2 aTexCoord;\n" +
            "varying vec2 tc;\n" +
            "void main()  {\n" +
            "   gl_Position = vec4(aPosition,0,1);\n" +
            "   tc = aTexCoord;\n" +
            "}\n"
    var fragmentSource = "precision mediump float;\n" +
            "varying vec2 tc;\n" +
            "uniform sampler2D sTexture;\n" +
            "void main() {\n" +
            "   gl_FragColor = texture2D(sTexture,tc);\n" +
            "}\n"


    internal var hPosition = 0
    internal var hTexCoord = 0

    internal var mProgram = 0

    override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {

        createTexture()
        //
        bufVertices = createFloatBuffer(mVertices)
        bufCoords = createFloatBuffer(mCoords)
        //
        mProgram = ShaderUtils.createProgram(vertexSource, fragmentSource)


        try {
            hPosition = getAttrib(mProgram, "aPosition")
            hTexCoord = getAttrib(mProgram, "aTexCoord")
        } catch (e: Exception) {
            e.printStackTrace()
        }


    }

    override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {

    }

    override fun onDrawFrame(gl: GL10) {

        if (mProgram == 0) {
            //            Log.e(">>>", "program==0");
            return
        }

        try {

            GLES20.glUseProgram(mProgram)
            //            ShaderUtils.checkGLError("glUseProgram");

            //            imageTexture.applyTexture();
            if (textureId > 0) {
                GLES20.glActiveTexture(textureId)
                onDraw(textureId)
            }

            applyAttrib(hPosition, 2, bufVertices)
            applyAttrib(hTexCoord, 2, bufCoords)

            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4)


        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    @Throws(Exception::class)
    internal fun getAttrib(prog: Int, attrName: String): Int {
        val h_pos = GLES20.glGetAttribLocation(prog, attrName)
        while (GLES20.glGetError() != GLES20.GL_NO_ERROR) {
            throw Exception("glGetAttribLocation \${attrName} -> prog = \${prog}, pos = \${GLES20.glGetError()}")
        }
        return h_pos
        //checkGLError(String.format("glGetAttribLocation %s -> prog = %d, pos = %d", attrName, prog, h_pos))
    }


    @Throws(Exception::class)
    internal fun applyAttrib(h: Int, SIZE: Int, floatBuffer: ByteBuffer) {
        val STRIP = SIZE * 4 //对齐数
        //Log.d("KKK","${attrName}, s=${SIZE},t=${STRIP}")
        GLES20.glVertexAttribPointer(h, SIZE, GLES20.GL_FLOAT, false, STRIP, floatBuffer)
        while (GLES20.glGetError() != GLES20.GL_NO_ERROR) {
            throw Exception("--->")
        }
        GLES20.glEnableVertexAttribArray(h)
        while (GLES20.glGetError() != GLES20.GL_NO_ERROR) {
            throw Exception("--->")
        }
    }


    internal fun createFloatBuffer(ff: FloatArray): ByteBuffer {
        val b = ByteBuffer.allocateDirect(ff.size * 4)
        b.order(ByteOrder.nativeOrder())
        val fb = b.asFloatBuffer()
        fb.put(ff)
        return b
    }

    private fun genTexture(): Int {
        val tex = intArrayOf(0)
        GLES20.glGenTextures(1, tex, 0)
        return tex[0]
    }

    fun createTexture() {
        textureId = genTexture()

        GLES20.glActiveTexture(textureId)

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)
//        ShaderUtils.checkGLErrorNoThrow("glBindTexture "+textureId);

        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR.toFloat())
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat())
        //
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE)
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE)


        val N = 640 * 480 * 3;
        val data = ByteBuffer.allocateDirect(N)
        for (i in 0 until N) {
            data.put(255.toByte())
        }
        val _fmt = GLES20.GL_RGB

        data.position(0)
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, _fmt, w, h, 0, _fmt, GLES20.GL_UNSIGNED_BYTE, data)
        ShaderUtils.checkGLErrorNoThrow("glTexImage2D")


    }


}
